#include <communication/Commuation.h>
#include <threadunit/TestSram.h>
#include <jsonrpc/Icore.h>
#include "string.h"
#include "cJSON.h"

rt_uint8_t Commuation::buf[1024] = {0};
vector<ThreadUnit *> Commuation::unitList;

/**
 * @brief entry of Commuation thread
 * @param parameter NULL
 */
void entry(void *parameter)
{
    Commuation comm;
    while (1)
    {
        rt_thread_mdelay(1000);
        //        rt_kprintf("Commuation\r\n");
    }
}

/**
 * @brief Commuation thread initiazation
 * @param  void
 * @return always 1
 */
int comm_init(void)
{
    rt_thread_t tid1 = RT_NULL;
    tid1 = rt_thread_create("Commuation", entry, NULL, 2048, 20, 10);
    if (tid1 != RT_NULL)
    {
        rt_thread_startup(tid1);
    }

    return 1;
}

/* 组件初始化方式要求初始化函数主动通过一些宏接口进行申明，链接器会自动收集所有被申明的初始化函数，放到特定的数据段中，数据段中的所有函数在系统初始化时会被调用。*/
// INIT_APP_EXPORT(comm_init); // will add function to system initialization

/**
 * @brief constructor of Commuation, create tcpserver
 */
Commuation::Commuation()
{
    comm = tcpserver_create(RT_LWIP_IPADDR, port);
    tcpserver_set_notify_callback(comm, commNotify);

    Icore &icore = Icore::getInstance();
    unitList.push_back(icore.sram);
    unitList.push_back(icore.modbusSystem);
}

/**
 * @brief unused destructor of Commuation
 */
Commuation::~Commuation()
{
}

/**
 * @brief deal with tcp event（处理不同的tcp事件）
 * @param client tcpclient_t, used in tcpserver（tcpserver中的客户端）
 * @param event totally 3 events: connect, disconnect, recv
 */
void Commuation::commNotify(tcpclient_t client, rt_uint8_t event)
{
    int ret;
    switch (event)
    {
    case TCPSERVER_EVENT_CONNECT:
        // rt_kprintf("tcpserver connect:%d\r\n", client->sock);
        break;
    case TCPSERVER_EVENT_DISCONNECT:
        // rt_kprintf("client disconnect:%d\r\n", client->sock);
        break;
    case TCPSERVER_EVENT_RECV:
        ret = tcpserver_recv(client, buf, 1024, -1);
        if (ret > 0)
        {
            rt_thread_mdelay(5);
            unpack(buf, ret);
            ret = tcpserver_send(client, buf, ret, 0);
        }
        break;
    default:
        rt_kprintf("unknown failed!\r\n");
        break;
    }
}

/**
 * @brief unpack the received data, and call recv() in this->unitList, use the message queue to send
 * （解析接收到的数据，并调用this->unitList里的recv函数，使用消息队列将其发送出去）
 * @param buf data buffer（数据内容）
 * @param len data length（数据长度）
 * @return RT_EOK if success, -1 if failed
 */
int Commuation::unpack(const unsigned char *buf, size_t len)
{
    cJSON *json, *json_id, *json_methodName, *json_serviceName;
    json = cJSON_Parse((const char *)buf);
    if (NULL == json)
    {
        return -1;
    }

    json_id = cJSON_GetObjectItem(json, "id");
    if (json_id->type == cJSON_Number)
    {
        // LOG_D("id: %d\n", json_id->valueint);
    }

    json_serviceName = cJSON_GetObjectItem(json, "serviceName");
    if (json_serviceName->type == cJSON_String)
    {
        // rt_kprintf("serviceName: %s\n", json_serviceName->valuestring);
    }

    json_methodName = cJSON_GetObjectItem(json, "methodName");
    if (json_methodName->type == cJSON_String)
    {
        // LOG_D("methodName: %s\n", json_methodName->valuestring);
    }

    int FindFlag = 0;
    struct msg msg_ptr;
    void *data = rt_malloc(len);

    if (data == RT_NULL)
    {
        rt_kprintf("rt_malloc error!\r\n");
        return -1;
    }
    rt_memcpy(data, buf, len);
    msg_ptr.data_ptr = (rt_uint8_t *)data; /* 指向相应的数据块地址 */
    msg_ptr.data_size = len;               /* 数据块的长度 */

    for (unsigned int var = 0; var < unitList.size(); ++var)
    {
        if (strcmp(json_serviceName->valuestring, unitList[var]->FunName) == 0)
        {
            FindFlag = 1;
            int result = unitList[var]->recv(msg_ptr);
            if (result != RT_EOK)
            {
                // LOG_E("rt_mq_send ERR\n");
                rt_free(msg_ptr.data_ptr);
            }
        }
    }

    if (FindFlag == 0)
    {
        rt_free(msg_ptr.data_ptr);
    }

    cJSON_Delete(json);
    return RT_EOK;
}
